package de.lgohlke.helper;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * for recursively walking a directory tree
 *
 * @author lars
 * @version $Id: $
 */
public class HibernateEntityFinder extends DirectoryWalker
{
  private final static Logger log = LoggerFactory.getLogger(HibernateEntityFinder.class);

  private final int           depthLimit;
  private File                basePath;

  /**
   * <p>Constructor for HibernateEntityFinder.</p>
   *
   * @param depthLimit
   *          limit to go into the hierarchy of the directories
   */
  public HibernateEntityFinder(final int depthLimit)
  {
    super(null, depthLimit);
    this.depthLimit = depthLimit;
  }

  /**
   * <p>Constructor for HibernateEntityFinder.</p>
   */
  public HibernateEntityFinder()
  {
    this(-1);
  }

  /**
   * <p>find.</p>
   *
   * @param startDirectory
   *          directory to search for eclipse projects
   * @throws java.io.IOException if any.
   * @throws EclipseException if any.
   * @return a {@link java.util.Set} object.
   */
  public Set<Class<?>> find(final File startDirectory) throws IOException
  {

    basePath = new File(FilenameUtils.normalizeNoEndSeparator(startDirectory.getAbsolutePath()));

    Set<Class<?>> results = new HashSet<Class<?>>();
    {

      debug("starting here: " + basePath.getAbsolutePath());
      debug("depth limit is : " + depthLimit);

      walk(basePath, results);
    }

    return results;
  }

  /** {@inheritDoc} */
  @Override
  protected boolean handleDirectory(final File directory, final int depth, @SuppressWarnings("rawtypes") final Collection results)
  {
    return !directory.getName().startsWith(".");
  }

  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  @Override
  protected void handleFile(final File file, final int depth, @SuppressWarnings("rawtypes") final Collection results)
  {
    if (file.getName().endsWith(".java"))
    {
      debug(file.getAbsolutePath());
      String path = file.getAbsoluteFile().toString().replaceFirst("^" + basePath.getAbsolutePath() + "/", "");
      path = path.replaceFirst("\\.java$", "");
      path = path.replaceAll("\\/", ".");

      try
      {
        results.add(Class.forName(path));
      }
      catch (ClassNotFoundException e)
      {
        // TODO Auto-generated catch block
        log.error(e.getMessage(), e);
      }
    }
  }

  private void debug(final String string)
  {
    if (log.isDebugEnabled())
    {
      log.debug("[" + getClass() + "]" + string);
    }

  }

  /**
   * <p>main.</p>
   *
   * @param args an array of {@link java.lang.String} objects.
   * @throws java.io.IOException if any.
   */
  public static void main(final String[] args) throws IOException
  {
    HibernateEntityFinder finder = new HibernateEntityFinder();
    // Set<Class<?>> list =
    finder.find(new File("src"));

    // for (Class<?> c : list)
    // {
    // System.out.println(c.getCanonicalName());
    // }

  }
}
